<?php

/**
 * @package Nina
 * @author John Main <john@thedaddy.org>
 */
class Nina_Utils {

	/**
	 * Check if an object is newer than another
	 * @param array $obj1 The first object
	 * @param array $obj2 The second object
	 * @return boolean
	 */
	public static function isNewer($obj1, $obj2) {
		return (strtotime($obj1->getUpdatedAt()) > strtotime($obj2->getUpdatedAt()));
	}

	/**
	 * Compare sets of complex objects
	 * @param array $set1 The first record set
	 * @param array $set2 The second record set
	 * @param string $method1 The compare method for set one
	 * @param string [$method2=null] The compare method for set two
	 * @return array
	 */
	public static function compareRecordSet($set1, $set2, $method1, $method2 = null) {
		if(!$method2)
			$method2 = $method1;

		$method1 = 'get'.ucfirst($method1);
		$method2 = 'get'.ucfirst($method2);
			
		$joined_records_1 = array();
		$joined_records_2 = array();

		foreach($set1 as $joined) {
			$joined_records_1[] = $joined->method1();
		}

		foreach($set2 as $joined) {
			$joined_records_2[] = $joined->method2();
		}
		
		//Exactly the same
		if($joined_records_1 === $joined_records_2)
			return true;
		//Different Order
		elseif($joined_records_1 == $joined_records_2)
			return false;
		//More records in set 1
		elseif(count($joined_records_1) > count($joined_records_2))
			return array(true, array_diff($joined_records_1, $joined_records_2));
		//More records in set 2
		else
			return array(false, array_diff($joined_records_2, $joined_records_1));
	}

	/**
	 * Parse the URLS and linebreaks within a piece of text
	 * @param string $text The text
	 * @return string
	 */
	public static function parseUrl($text) {

		$pattern = '/((https?:\/\/)?([-\w]+\.[-\w\.]+)+\w(:\d+)?(\/([-\w\/_\.]*(\?\S+)?)?)*)/';
		$replace = '<a href="$1">$1</a>';
		$text = preg_replace($pattern, $replace, $text);
		
		return nl2br($text);
	}
	
	/**
	 * Get the first N Lines of a piece of text
	 * @param string $text The text
	 * @return string
	 */
	public static function firstNLines($text, $no_of_lines = 1) {
		$ct = 0;
		$pos = 0;
		while (($pos = strpos($text, "\n", $pos)) !== false) {
			if (++$ct == $no_of_lines) {
				return substr($text, 0, $pos);
			}
	
			$pos++;
		}

		return $text;
	} 

	/**
	 * Convert a digit to a roman numeral
	 * @return array
	 */
	public static function getNumeral($number) {
	
		// Make sure that we only use the integer portion of the value
		$number = intval($number);
		$result = '';
	
		// Declare a lookup array that we will use to traverse the number:
		$lookup = array('m' => 1000, 'cm' => 900, 'd' => 500, 'cd' => 400,
		'c' => 100, 'xc' => 90, 'l' => 50, 'xl' => 40,
		'x' => 10, 'ix' => 9, 'v' => 5, 'iv' => 4, 'i' => 1);
	
		foreach ($lookup as $roman => $value) 
		{
			// Determine the number of matches
			$matches = intval($number / $value);
	
			// Store that many characters
			$result .= str_repeat($roman, $matches);
	
			// Substract that from the number
			$number = $number % $value;
		}
	
		// The Roman numeral should be built, return it
		return $result;
	}

	/**
	 * Recursively require all files under a directory
	 * @param string $directory Directory to start from
	 */
	public static function requireAll($directory) {
		if($handle = opendir($directory)) {
			$directories = array();
		
			while (false !== ($file = readdir($handle))) {
				if($file{0} != ".") {
					if(!is_dir($directory.DIRECTORY_SEPARATOR.$file))
						require_once $directory.DIRECTORY_SEPARATOR.$file;
					else
						array_push($directories, $directory.DIRECTORY_SEPARATOR.$file);
				}
			}
		
			closedir($handle);
		
			while(count($directories) > 0) {
				self::requireAll(array_pop($directories));
			}
		}
	}

	/**
	 * Convert a class name to a table name (given classic naming convention)
	 * @param string $class_name The class name
	 * @return string
	 */
	public static function classToTableName($class_name) {
		$table_name = Nina_String::doUnderscore($class_name);
		return Nina_Inflect::pluralizeUnderscore($table_name);
	}
	
	/**
	 * Convert a table name to a class name (given classic naming convention)
	 * @param string $table_name The table name
	 * @return string
	 */
	public static function tableToClassName($table_name) {
		$class_name = Nina_Inflect::singularizeUnderscore($table_name);
		return Nina_String::doCamelize($class_name);
	}	
	
	/**
	 * Check if a directory is writable (try to create if it doesn't already exist)
	 * @param string $path The path to the directory
	 * @return boolean
	 */
	public static function writableDir($path) {
		return ((is_dir($path) || @mkdir($path)) && is_writable($path));
	}
	
	/**
	 * Clear a directory
	 * @param string $path The path to the directory
	 * @param boolean [$remove_top_level=false] Remove the top level directory too
	 */
	public static function clearDir($path, $remove_top_level = false) {
		if(is_dir($path)) {
			foreach(scandir($path) as $element) {
				if($element != '.' && $element != '..')
					(is_dir($path . DIRECTORY_SEPARATOR . $element)) ? self::clearDir($path . DIRECTORY_SEPARATOR . $element, true) : unlink($path . DIRECTORY_SEPARATOR . $element);
			}
			
			if($remove_top_level)
				rmdir($path);
		}
	}
}